package cn.mw.cmdb.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.mw.cmdb.api.BusinessIdUserInfo;
import cn.mw.cmdb.async.DatasourceAsyncScanService;
import cn.mw.cmdb.config.CustomizeThreadPool;
import cn.mw.cmdb.entity.*;
import cn.mw.cmdb.enums.DatasourceScanStatusEnum;
import cn.mw.cmdb.enums.MonitoringServerType;
import cn.mw.cmdb.enums.ZabbixAssetsStatusEnum;
import cn.mw.cmdb.mongoMapper.DatasourceSyncInstanceInfoMapper;
import cn.mw.cmdb.mongoMapper.DatasourceSyncResultInfoMapper;
import cn.mw.cmdb.param.*;
import cn.mw.cmdb.processor.BusinessProcessNetwork;
import cn.mw.cmdb.processor.MonitorProcessor;
import cn.mw.cmdb.service.InstanceSyncService;
import cn.mw.cmdb.service.ModelService;
import cn.mw.cmdb.service.MwMonitorProcessorConvert;
import cn.mw.cmdb.util.AssetsTool;
import cn.mw.cmdb.util.CMDBScanEngineTool;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.cmdb.util.SnmpSearchContext;
import cn.mw.cmdb.view.ViewConvertContext;
import cn.mw.cmdb.view.ViewManager;
import cn.mw.components.mongodb.entity.CriteriaOpsType;
import cn.mw.components.mongodb.entity.SearchParam;
import cn.mw.components.mongodb.entity.SubCondition;
import cn.mw.components.mongodb.tool.CriteriaWrapper;
import cn.mw.microMonitorCommon.api.cmdb.*;
import cn.mw.microMonitorCommon.api.common.MwEngineManageService;
import cn.mw.microMonitorCommon.api.scan.AssetScanService;
import cn.mw.microMonitorCommon.api.scan.RuleParam;
import cn.mw.microMonitorCommon.entity.cmdb.DataSourceInstanceVo;
import cn.mw.microMonitorCommon.entity.cmdb.DataSourceSyncResultVo;
import cn.mw.microMonitorCommon.entity.cmdb.DataSourceVo;
import cn.mw.microMonitorCommon.entity.cmdb.MwMacOuiVo;
import cn.mw.microMonitorCommon.entity.ipam.IpScanAssetsDto;
import cn.mw.microMonitorCommon.enums.DatasourceSyncMethodEnum;
import cn.mw.microMonitorCommon.enums.RuleType;
import cn.mw.microMonitorCommon.util.IDModelType;
import cn.mw.microMonitorCommon.util.ModuleIDManager;
import cn.mw.microMonitorCommon.util.SpringUtils;
import cn.mw.scanengine.service.ScanEngineService;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.Future;
import java.util.function.Function;

import static cn.mw.cmdb.entity.PropertyType.relationIdKey;
import static cn.mw.cmdb.entity.PropertyType.relationNameKey;
import static cn.mw.cmdb.processor.TreeProcessorBusiness.modelClassify;
import static cn.mw.cmdb.processor.TreeProcessorBusiness.modelSystem;
import static cn.mw.cmdb.service.impl.InstanceServiceImpl.alertLevelList;


@DubboService
@Slf4j
public class AssetsServiceImpl implements AssetsService {

    private CmdbServiceManage cmdbServiceManage;

    private TableHeaderAndDataManage tableHeaderAndDataManage;

    private ViewManager viewManager;

    private ModuleIDManager moduleIDManager;

    private DatasourceSyncResultInfoMapper datasourceSyncResultInfoMapper;

    private DatasourceSyncInstanceInfoMapper datasourceSyncInstanceInfoMapper;

    private BusinessProcessNetwork businessProcessNetwork;

    private ScanEngineService scanEngineService;

    private DatasourceAsyncScanService datasourceAsyncScanService;

    @DubboReference(check = false, mock = "true", timeout = 15000)
    private MwEngineManageService mwEngineManageService;

    public AssetsServiceImpl(CmdbServiceManage cmdbServiceManage, TableHeaderAndDataManage tableHeaderAndDataManage
            , ViewManager viewManager, ModuleIDManager moduleIDManager, DatasourceSyncResultInfoMapper datasourceSyncResultInfoMapper
            , DatasourceSyncInstanceInfoMapper datasourceSyncInstanceInfoMapper, BusinessProcessNetwork businessProcessNetwork
            , ScanEngineService scanEngineService, DatasourceAsyncScanService datasourceAsyncScanService) {
        this.cmdbServiceManage = cmdbServiceManage;
        this.tableHeaderAndDataManage = tableHeaderAndDataManage;
        this.viewManager = viewManager;
        this.moduleIDManager = moduleIDManager;
        this.datasourceSyncResultInfoMapper = datasourceSyncResultInfoMapper;
        this.datasourceSyncInstanceInfoMapper = datasourceSyncInstanceInfoMapper;
        this.businessProcessNetwork = businessProcessNetwork;
        this.scanEngineService = scanEngineService;
        this.datasourceAsyncScanService = datasourceAsyncScanService;
    }

    @DubboReference(check = false, timeout = 120000, mock = "true")
    private AssetScanService assetScanService;

    @Override
    public List<AssetInfo> searchAssets(AssetsSearchParam param) throws Exception {
        InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        InstanceSearchParam instanceSearchParam = new InstanceSearchParam();

        if(null != param.getIgnoreLogicDel()){
            instanceSearchParam.setIgnoreLogicDel(param.getIgnoreLogicDel());
        }

        //资产实例Id查询
        if (StringUtils.hasText(param.getId())) {
            instanceSearchParam.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getId)
                    , new SubCondition(CriteriaOpsType.is.name(), param.getId()));
        }
        //资产实例Id查询
        if (!CollectionUtils.isEmpty(param.getIds())) {
            instanceSearchParam.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getId)
                    , new SubCondition(CriteriaOpsType.in.name(), param.getIds()));
        }
        //分组、模型id查询
        if (StringUtils.hasText(param.getGroupOrModelId())) {
            instanceSearchParam.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getPath)
                    , new SubCondition(CriteriaOpsType.in.name(), param.getGroupOrModelId()));
        }

        List<String> modelIds = param.getModelIds();
        if (null != modelIds && !modelIds.isEmpty()) {
            instanceSearchParam.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getModelId)
                    , new SubCondition(CriteriaOpsType.in.name(), modelIds));
        }
        List<String> modelSystemIds = param.getModelSystemId();
        if (!CollectionUtils.isEmpty(modelSystemIds)) {
            instanceSearchParam.addSubCondition(modelSystem
                    , new SubCondition(CriteriaOpsType.in.name(), modelSystemIds));
        }

        List<String> modelClassifyIds = param.getModelClassifyId();
        if (!CollectionUtils.isEmpty(modelClassifyIds)) {
            instanceSearchParam.addSubCondition(modelClassify
                    , new SubCondition(CriteriaOpsType.in.name(), modelClassifyIds));
        }

        List<String> modelGroupIds = param.getModelGroupIds();
        if (null != modelGroupIds && !modelGroupIds.isEmpty()) {
            instanceSearchParam.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getPath)
                    , new SubCondition(CriteriaOpsType.elemMatch.name(), modelGroupIds));
        }
        //负责人id查询
        if (null != param.getUserId()) {
            instanceSearchParam.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getUsers)
                    , new SubCondition(CriteriaOpsType.in.name(), param.getUserId()));
        }
        //负责人ids查询
        if (null != param.getUserIds()) {
            instanceSearchParam.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getUsers)
                    , new SubCondition(CriteriaOpsType.in.name(), param.getUserIds()));
        }
        //资产名称查询
        if (null != param.getInstanceName()) {
            instanceSearchParam.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getInstanceName)
                    , new SubCondition(CriteriaOpsType.like.name(), param.getInstanceName()));
        }

        //资产ip查询
        if (null != param.getInBandIp()) {
            if (param.isEnableKeyword()) {
                instanceSearchParam.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getInBandIp)
                        , new SubCondition(CriteriaOpsType.like.name(), param.getInBandIp()));
            } else {
                instanceSearchParam.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getInBandIp)
                        , new SubCondition(CriteriaOpsType.is.name(), param.getInBandIp()));
            }
        }

        //资产ip查询
        if (null != param.getIpList()) {
            instanceSearchParam.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getInBandIp)
                    , new SubCondition(CriteriaOpsType.in.name(), param.getIpList()));
        }

        //模型类型查询
        if (!CollectionUtils.isEmpty(param.getModelTypes())) {
            instanceSearchParam.addSubCondition(CMDBTool.getFieldName(InstanceInfoExtend::getModelType)
                    , new SubCondition(CriteriaOpsType.in.name(), param.getModelTypes()));
        }

        if (StringUtils.hasText(param.getOperation())) {
            instanceSearchParam.setOperation(param.getOperation());
        }

        List<InstanceInfoExtend> instanceInfos = new ArrayList<>();
        instanceInfos = instanceService.aggregateList(instanceSearchParam);
        if (null != instanceInfos) {
            if (param.isEnableAssetsStatus()) {
                instanceService.getInstanceAlertInfo(instanceInfos);
            }
            List<AssetInfo> assetInfos = convertParam(instanceInfos, param.isEnableAssetsStatus());
            return assetInfos;
        }

        return null;
    }

    @Override
    public List<ModelInfoCommonView> listModelInfo(String modelGroupId) throws Exception {
        if (!StringUtils.hasText(modelGroupId)) {
            return null;
        }
        CustomModelServiceImpl customModelService = (CustomModelServiceImpl) cmdbServiceManage.getModelService(CustomModelServiceImpl.ID);
        List<String> modelGroupIds = new ArrayList<>();
        modelGroupIds.add(modelGroupId);
        List<ModelInfo> modelInfos = customModelService.findModelListByGroups(modelGroupIds);
        List<ModelInfoCommonView> views = null;
        if (null != modelInfos) {
            views = new ArrayList<>();
            for (ModelInfo modelInfo : modelInfos) {
                ModelInfoCommonView view = new ModelInfoCommonView(modelInfo.getId()
                        , modelInfo.getModelName(), modelInfo.getGroupId(), modelInfo.getGroupPath());
                views.add(view);
            }
            return views;
        }
        return null;
    }

    @Override
    public List<AssetCatolog> listAssetCatolog(AssetCatologParam assetCatologParam) throws Exception {
        TableSearchParam tableSearchParam = new TableSearchParam();
        tableSearchParam.setTableId(TableIdEnum.assetType.getCode());
        List<TreeView> treeViewList = tableHeaderAndDataManage.listTree(tableSearchParam);
        ViewConvertContext context = new ViewConvertContext();
        context.setHideStatusFlag(assetCatologParam.getIsHideStatus());
        List<TreeView> ret = (List) viewManager.getTreeViewObject(treeViewList, context);
        List<AssetCatolog> list = new ArrayList<>();
        if (!StringUtils.hasText(assetCatologParam.getId()) && !StringUtils.hasText(assetCatologParam.getName())) {
            for (TreeView treeView : ret) {
                AssetCatolog assetCatolog = AssetsTool.convertFrom(treeView);
                list.add(assetCatolog);
            }
        } else {
            TreeView root = CMDBTool.getSubTree(assetCatologParam.getId(), assetCatologParam.getName(), ret);
            AssetCatolog assetCatolog = AssetsTool.convertFrom(root);
            list.add(assetCatolog);
        }

        return list;
    }

    /**
     * 获取基础设置树结构
     *
     * @param assetCatologParam
     * @return
     * @throws Exception
     */
    @Override
    public List<AssetCatolog> getBaseAssetsTree(AssetCatologParam assetCatologParam) throws Exception {
        TableSearchParam tableSearchParam = new TableSearchParam();
        tableSearchParam.setTableId(TableIdEnum.model.getCode());
        String baseGroupId = SpringUtils.getPropertiesValue("base.groupId");
        Map<String, SubCondition> condition = new HashMap<>();
        List<SearchParam> searchParamList = new ArrayList<>();
        TableSearchParam sub1 = new TableSearchParam();
        sub1.setOperation(CriteriaOpsType.and.name());
        condition.put(CMDBTool.getFieldName(ModelGroupInfo::getId), new SubCondition(CriteriaOpsType.is.name(), baseGroupId));
        sub1.setCondition(condition);
        searchParamList.add(sub1);

        TableSearchParam sub2 = new TableSearchParam();
        sub1.setOperation(CriteriaOpsType.and.name());
        condition = new HashMap<>();
        condition.put(CMDBTool.getFieldName(ModelGroupInfo::getPath), new SubCondition(CriteriaOpsType.in.name(), baseGroupId));
        sub2.setCondition(condition);
        searchParamList.add(sub2);

        TableSearchParam sub3 = new TableSearchParam();
        sub1.setOperation(CriteriaOpsType.and.name());
        condition = new HashMap<>();
        condition.put(CMDBTool.getFieldName(ModelInfo::getGroupPath), new SubCondition(CriteriaOpsType.in.name(), baseGroupId));
        sub3.setCondition(condition);
        searchParamList.add(sub3);

        tableSearchParam.setOperation(CriteriaOpsType.or.name());
        tableSearchParam.setSearchParamList(searchParamList);

        List<TreeView> treeViewList = tableHeaderAndDataManage.listTree(tableSearchParam);
        ViewConvertContext context = new ViewConvertContext();
        context.setHideStatusFlag(assetCatologParam.getIsHideStatus());
        List<TreeView> ret = (List) viewManager.getTreeViewObject(treeViewList, context);
        List<AssetCatolog> list = new ArrayList<>();
        if (!StringUtils.hasText(assetCatologParam.getId()) && !StringUtils.hasText(assetCatologParam.getName())) {
            for (TreeView treeView : ret) {
                AssetCatolog assetCatolog = AssetsTool.convertFrom(treeView);
                list.add(assetCatolog);
            }
        } else {
            TreeView root = CMDBTool.getSubTree(assetCatologParam.getId(), assetCatologParam.getName(), ret);
            AssetCatolog assetCatolog = AssetsTool.convertFrom(root);
            list.add(assetCatolog);
        }

        return list;
    }


    /**
     * 定时任务执行批量更新资产状态
     *
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public boolean batchUpdateAssetStatus(Map<String, Object> map) throws Exception {
        InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        // 按照状态进行批量更新
        BatchEditorViewInstance batchEditorViewInstance = JSON.parseObject(JSON.toJSONString(map), BatchEditorViewInstance.class);
        //设置为定时任务执行
        batchEditorViewInstance.setTimeTaskFlag(true);
        instanceService.batchUpdate(batchEditorViewInstance);
        return true;
    }

    @Override
    public List<BusinessIdUserInfo> findUserIdsByInstanceId(List<String> ids) throws Exception {
        List<BusinessIdUserInfo> instanceDataInfos = new ArrayList<>();
        InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        InstanceSearchParam instanceSearchParam = new InstanceSearchParam();
        SubCondition subCondition = new SubCondition(CriteriaOpsType.in.name(), ids);
        instanceSearchParam.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getId), subCondition);

        List<String> fields = new ArrayList<>();
        fields.add(CMDBTool.getFieldName(InstanceInfo::getId));
        fields.add(CMDBTool.getFieldName(InstanceInfo::getUsers));
        instanceSearchParam.setFields(fields);
        List<InstanceInfo> instanceInfos = instanceService.doSelectList(instanceSearchParam);
        if (null != instanceInfos) {
            for (InstanceInfo instanceInfo : instanceInfos) {
                BusinessIdUserInfo info = new BusinessIdUserInfo();
                info.setInstanceId(instanceInfo.getId());
                info.setUsers(instanceInfo.getUsers());
                instanceDataInfos.add(info);
            }
        }
        return instanceDataInfos;
    }

    @Override
    public List<ModelInfoCommonView> findModelInfoByIds(List<String> ids) throws Exception {
        if (CollectionUtils.isEmpty(ids)) {
            return null;
        }
        CustomModelServiceImpl customModelService = (CustomModelServiceImpl) cmdbServiceManage.getModelService(CustomModelServiceImpl.ID);
        List<ModelInfo> modelInfos = customModelService.findByIds(ids);
        List<ModelInfoCommonView> views = null;
        if (null != modelInfos) {
            views = new ArrayList<>();
            for (ModelInfo modelInfo : modelInfos) {
                ModelInfoCommonView view = new ModelInfoCommonView(modelInfo.getId()
                        , modelInfo.getModelName(), modelInfo.getGroupId(), modelInfo.getGroupPath());
                views.add(view);
            }
            return views;
        }
        return null;
    }

    @Override
    public List<ItemNameMapperParam> getItemNameMappingInfo(ItemNameMapperParam param) throws Exception {
        MwMonitorProcessorConvert processorConvert = new MwMonitorProcessorConvert();
        String type = param.getType();
        if (Strings.isNullOrEmpty(type)) {
            //默认查询zabbix监控服务
            type = MonitoringServerType.Zabbix.name();
        }
        MonitoringServerType monitoringServerType = MonitoringServerType.valueOf(type);
        //获取查询监控processor
        MonitorProcessor processor = processorConvert.getMonitorProcessor(monitoringServerType);
        ItemNameMapperInfo itemNameMapperInfo = new ItemNameMapperInfo();
        BeanUtil.copyProperties(param, itemNameMapperInfo, CopyOptions.create().setIgnoreNullValue(true));
        List<ItemNameMapperInfo> itemNameMapperList = processor.getItemNameMapperList(itemNameMapperInfo);
        List<ItemNameMapperParam> list = new ArrayList<>();
        for (ItemNameMapperInfo itemInfo : itemNameMapperList) {
            ItemNameMapperParam itemNameMapperParam = new ItemNameMapperParam();
            //忽略null值注入
            BeanUtil.copyProperties(itemInfo, itemNameMapperParam, CopyOptions.create().setIgnoreNullValue(true));
            itemNameMapperParam.setItem(itemInfo.getZabbixItem());
            list.add(itemNameMapperParam);
        }
        return list;
    }

    @Override
    public DataSourceSyncResultVo batchSyncInstance(DataSourceVo datasourceVo, List<DataSourceInstanceVo> list) throws Exception {
        DataSourceSyncResultVo dataSourceSyncResultVo = new DataSourceSyncResultVo();
        dataSourceSyncResultVo.setTaskId(moduleIDManager.getIDStr(IDModelType.Model));
        // 同步结果保存数据库
        DataSourceSyncResultInfo dataSourceSyncResultInfo = new DataSourceSyncResultInfo();
        dataSourceSyncResultInfo.setDataSourceId(datasourceVo.getId());
        dataSourceSyncResultInfo.setId(dataSourceSyncResultVo.getTaskId());
        dataSourceSyncResultInfo.setSyncTime(new Date());
        if (!CollectionUtils.isEmpty(list)) {
            DatasourceSyncMethodEnum datasourceSyncMethodEnum = datasourceVo.getSyncMethod();
            List<InstanceSyncService> instanceSyncServiceList = SpringUtils.getApplicationContext().getBeansOfType(InstanceSyncService.class).values()
                    .stream().filter(item -> item.getDatasourceSyncMethodEnum().equals(datasourceSyncMethodEnum)).toList();
            if (!CollectionUtils.isEmpty(instanceSyncServiceList)) {
                list.forEach(item -> {
                    Map<String, Object> instanceParams = item.getInstanceParams();
                    instanceParams.put(CMDBTool.getFieldName(InstanceInfo::getOrgs), datasourceVo.getOrgs());
                    instanceParams.put(CMDBTool.getFieldName(InstanceInfo::getUsers), datasourceVo.getUsers());
                    instanceParams.put(CMDBTool.getFieldName(InstanceInfo::getGroups), datasourceVo.getGroups());
                    instanceParams.put(CMDBTool.getFieldName(InstanceInfo::getModelId), datasourceVo.getTargetModelId());
                    if (!instanceParams.containsKey(CMDBTool.getFieldName(InstanceInfo::getBrandId))) {
                        instanceParams.put(CMDBTool.getFieldName(InstanceInfo::getBrandId), item.getHostIp());
                    }
                });
                List<DataSourceInstanceVo> dataSourceInstanceVoList = instanceSyncServiceList.get(0).syncInstances(datasourceVo, batchAddInstanceParamConvert(list));
                List<DataSourceInstanceVo> successSourceInstanceVoList = dataSourceInstanceVoList.stream().filter(DataSourceInstanceVo::isAsyncResult).toList();
                List<DataSourceInstanceVo> failedSourceInstanceVoList = dataSourceInstanceVoList.stream().filter(item -> !item.isAsyncResult()).toList();
                dataSourceSyncResultVo.setSuccessCount(successSourceInstanceVoList.size());
                dataSourceSyncResultVo.setFailedCount(failedSourceInstanceVoList.size());
                dataSourceSyncResultVo.setDatasourceId(datasourceVo.getId());
                dataSourceSyncResultInfo.setSuccessCount(dataSourceSyncResultVo.getSuccessCount());
                dataSourceSyncResultInfo.setFailedCount(dataSourceSyncResultVo.getFailedCount());
                datasourceSyncResultInfoMapper.save(dataSourceSyncResultInfo);
                datasourceSyncInstanceInfoMapper.insertAll(parseInstance(dataSourceInstanceVoList, dataSourceSyncResultVo.getTaskId()));
                // 使用异步任务自动扫描资产,根据扫描结果设置模板、厂商、型号等信息
                if (datasourceSyncMethodEnum != DatasourceSyncMethodEnum.syncDelete
                        && !CollectionUtils.isEmpty(successSourceInstanceVoList)) {
                    new Thread(() -> {
                        try {
                            datasourceAsyncScanService.asyncScan(successSourceInstanceVoList, datasourceVo, dataSourceSyncResultInfo.getId());
                        } catch (Exception e) {
                            log.error("asyncScan error!", e);
                        }
                    }).start();
                }
            }
        } else {
            datasourceSyncResultInfoMapper.save(dataSourceSyncResultInfo);
        }
        // 同步结果记录
        return dataSourceSyncResultVo;
    }

    @Override
    public List<AssetsInterfaceView> listAssetsInterfaces(QueryAssetsInterfaceParam queryAssetsInterfaceParam) throws Exception {

        List<AssetsInterfaceDTO> assetsInterfaceDTOS = null;
        if(StringUtils.hasText(queryAssetsInterfaceParam.getInstanceId())){
            assetsInterfaceDTOS = businessProcessNetwork.listAssetsInterfaces(queryAssetsInterfaceParam);
        }else if(null != queryAssetsInterfaceParam.getInstanceIds() && !queryAssetsInterfaceParam.getInstanceIds().isEmpty()){
            assetsInterfaceDTOS = businessProcessNetwork.listAssetsInterfaces(queryAssetsInterfaceParam.getInstanceIds());
        }

        if (null != assetsInterfaceDTOS) {
            List<AssetsInterfaceView> assetsInterfaceViews = new ArrayList<>();
            for (AssetsInterfaceDTO assetsInterfaceDTO : assetsInterfaceDTOS) {
                AssetsInterfaceView assetsInterfaceView = new AssetsInterfaceView();
                BeanUtil.copyProperties(assetsInterfaceDTO, assetsInterfaceView);
                if (!StringUtils.hasText(assetsInterfaceView.getAlias())) {
                    if (StringUtils.hasText(assetsInterfaceView.getDescription())) {
                        assetsInterfaceView.setAlias(assetsInterfaceView.getDescription());
                    } else {
                        assetsInterfaceView.setAlias(assetsInterfaceView.getName());
                    }
                }
                assetsInterfaceViews.add(assetsInterfaceView);
            }
            return assetsInterfaceViews;
        }
        return null;
    }

    @Override
    public List<IpScanAssetsDto> getIpScanAssetsList() throws Exception {
        // 查询运维监控实例
        List<String> topoGroupIds = getTopoModelGroupIDs();
        InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        Query query = new Query(CriteriaWrapper.where(InstanceInfo::getPath).elemMatch(new Criteria().in(topoGroupIds)));
        List<InstanceInfo> instanceInfoList = instanceService.selectListByQuery(query);
        Map<String, String> ip2InstanceIdMap = new HashMap<>();
        for (InstanceInfo instanceInfo : instanceInfoList) {
            ip2InstanceIdMap.put(instanceInfo.getInBandIp(), instanceInfo.getId());
        }

        ThreadPoolTaskExecutor executor = SpringUtils.getBean(CustomizeThreadPool.ScanThreadPool, ThreadPoolTaskExecutor.class);
        log.info("executor info ActiveCount:{},PoolSize:{},MaxPoolSize:{}", executor.getActiveCount(), executor.getPoolSize(), executor.getMaxPoolSize());

        List<Future<List<IpScanAssetsDto>>> futures = CMDBScanEngineTool.getScanData(scanEngineService, executor, instanceInfoList, new Function<SnmpSearchContext<AssetScanService>, List<IpScanAssetsDto>>() {
                    @Override
                    public List<IpScanAssetsDto> apply(SnmpSearchContext<AssetScanService> snmpSearchContext) {
                        AssetScanService assetScanService = snmpSearchContext.getSnmpScanService();
                        List<cn.mw.scanengine.snmp.param.SearchParam> searchParams = snmpSearchContext.getSearchParamList();
                        List<IpScanAssetsDto> ipScanAssetDTOList = null;
                        try {
                            ipScanAssetDTOList = assetScanService.getIpScanAssetsList(searchParams, ip2InstanceIdMap);
                        } catch (Exception e) {
                            log.error("getIpScanAssetsList", e);
                        }
                        return ipScanAssetDTOList;
                    }
                }
                , mwEngineManageService, IpScanAssetsDto.class, AssetScanService.class);

        List<IpScanAssetsDto> ret = new ArrayList<>();
        if (null != futures) {
            for (Future<List<IpScanAssetsDto>> future : futures) {
                List<IpScanAssetsDto> list = future.get();
                if (null != list) {
                    ret.addAll(list);
                }
            }
        }

        return ret;
    }

    @Override
    public List<String> getTopoModelGroupIDs() {
        // topo使用网络设备与安全设备snmp信息扫描
        return Arrays.asList(SpringUtils.getPropertiesValue("base.network.groupId"), SpringUtils.getPropertiesValue("base.safeEquip.groupId"));
    }

    private List<DataSourceSyncInstanceInfo> parseInstance(List<DataSourceInstanceVo> dataSourceInstanceVoList, String taskId) {
        List<DataSourceSyncInstanceInfo> result = new ArrayList<>();
        dataSourceInstanceVoList.forEach(item -> {
            DataSourceSyncInstanceInfo dataSourceSyncInstanceInfo = new DataSourceSyncInstanceInfo();
            dataSourceSyncInstanceInfo.setInstanceParams(item.getInstanceParams());
            dataSourceSyncInstanceInfo.setName(item.getName());
            dataSourceSyncInstanceInfo.setAsyncResult(item.isAsyncResult());
            dataSourceSyncInstanceInfo.setHostIp(item.getHostIp());
            dataSourceSyncInstanceInfo.setHostId(item.getHostId());
            dataSourceSyncInstanceInfo.setErrorMsg(item.getErrorMsg());
            dataSourceSyncInstanceInfo.setTaskId(taskId);
            dataSourceSyncInstanceInfo.setInstanceId(item.getInstanceId());
            dataSourceSyncInstanceInfo.setScanResult(DatasourceScanStatusEnum.init.desc);
            result.add(dataSourceSyncInstanceInfo);
        });
        return result;
    }

    private Map<DataSourceInstanceVo, InstanceInfo> batchAddInstanceParamConvert(List<DataSourceInstanceVo> list) throws Exception {
        Map<DataSourceInstanceVo, InstanceInfo> hostId2InstanceMap = new HashMap<>();
        ModelService modelService = cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        for (DataSourceInstanceVo dataSourceInstanceVo : list) {
            Map<String, Object> instanceParams = dataSourceInstanceVo.getInstanceParams();
            Object convert = cmdbServiceManage.convert(modelService, instanceParams);
            //将map参数转为InstanceInfo
            if (convert != null && convert instanceof InstanceInfo) {
                InstanceInfo instanceInfo = (InstanceInfo) convert;
                instanceInfo.setData(instanceParams);
                instanceInfo.setMonitorTypeId(dataSourceInstanceVo.getHostId());
                hostId2InstanceMap.put(dataSourceInstanceVo, instanceInfo);
            }
        }
        return hostId2InstanceMap;
    }

    public List<RuleParam> convertScanParam(InstanceInfo instanceInfo) {
        List<RuleParam> ruleParams = new ArrayList<>();
        RuleParam ruleParam = null;
        // 表示为ICMP 和agent
        String ruleType = instanceInfo.getRuleType();
        RuleType type = RuleType.getInfoByName(ruleType);
        switch (type) {
            case Agent -> ruleParam = new RuleParam(ruleType, String.valueOf(instanceInfo.getPort()));
            case SNMPv1, SNMPv2 ->
                    ruleParam = new RuleParam(ruleType, String.valueOf(instanceInfo.getPort()), instanceInfo.getCommunity());
            case SNMPv3 ->
                    ruleParam = new RuleParam(ruleType, instanceInfo.getContextName(), instanceInfo.getSecurityName()
                            , instanceInfo.getSecurityLevel(), instanceInfo.getAuthAlgName(), instanceInfo.getAuthValue()
                            , instanceInfo.getPrivAlgName(), instanceInfo.getPriValue()
                    );
        }
        if (ruleParam != null) {
            ruleParams.add(ruleParam);
        }
        return ruleParams;
    }

    @Override
    public List<MwMacOuiVo> getVendorsByMacList(List<String> macList) throws Exception {
        MacOuiSearchParam info = new MacOuiSearchParam();
        info.addSubCondition(CMDBTool.getFieldName(MwMacOuiInfo::getMac), new SubCondition(CriteriaOpsType.in.name(), macList));
        ModelMacOuiServiceImpl modelMacOuiService = (ModelMacOuiServiceImpl) cmdbServiceManage.getModelService(ModelMacOuiServiceImpl.ID);
        List<MwMacOuiInfo> mwMacOuiInfoList = modelMacOuiService.doSelectList(info);
        List<MwMacOuiVo> resultList = new ArrayList<>();
        MwMacOuiVo mwMacOuiVo;
        for (MwMacOuiInfo mwMacOuiInfo : mwMacOuiInfoList) {
            mwMacOuiVo = new MwMacOuiVo();
            mwMacOuiVo.setId(mwMacOuiInfo.getId());
            mwMacOuiVo.setMac(mwMacOuiInfo.getMac());
            mwMacOuiVo.setVendor(mwMacOuiInfo.getVendor());
            mwMacOuiVo.setShortName(mwMacOuiInfo.getShortName());
            resultList.add(mwMacOuiVo);
        }
        return resultList;
    }

    @Override
    public List<AssetInfo> getInstanceListByUserList(List<Long> userIds) throws Exception {
        InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        Query query = new Query(CriteriaWrapper.where(InstanceInfo::getUsers).in(userIds));
        List<InstanceInfo> instanceList = instanceService.selectListByQuery(query);
        List<AssetInfo> assetInfos = convertParam(instanceList, false);
        return assetInfos;
    }

    @Override
    public List<GroupModelInfo> getCmdbGroupModelInfo() throws Exception {
        TableSearchParam tableSearchParam = new TableSearchParam();
        tableSearchParam.setTableId(TableIdEnum.model.getCode());
        List<TreeView> datas = tableHeaderAndDataManage.listTree(tableSearchParam);
        List<GroupModelInfo> ret = new ArrayList<>();
        for (TreeView item : datas) {
            GroupModelInfo groupModelInfo = new GroupModelInfo();
            groupModelInfo.setId(item.getId().toString());
            groupModelInfo.setType(item.getType());
            groupModelInfo.setName(item.getItemName());
            ret.add(groupModelInfo);
        }
        return ret;
    }

    private List<AssetInfo> convertParam(List<? extends InstanceInfo> instanceInfos, boolean isEnableAssetsStatus) {
        List<AssetInfo> assetInfos = new ArrayList<>();
        for (InstanceInfo instanceInfo : instanceInfos) {
            //秘钥解密
            instanceInfo.decryptInfo();
            AssetInfo assetInfo = new AssetInfo();
            assetInfo.setId(instanceInfo.getId());
            assetInfo.setModelId(instanceInfo.getModelId());
            assetInfo.setGroupId(instanceInfo.getGroupId());
            assetInfo.setName(instanceInfo.getInstanceName());
            assetInfo.setInstanceName(instanceInfo.getInstanceName());
            if (instanceInfo instanceof InstanceInfoExtend) {
                assetInfo.setGroupName(((InstanceInfoExtend) instanceInfo).getModelGroupName());
                assetInfo.setModelName(((InstanceInfoExtend) instanceInfo).getModelName());
            }
            assetInfo.setMonitoringServerType(instanceInfo.getMonitorType());
            assetInfo.setTypeId(instanceInfo.getMonitorTypeId());
            assetInfo.setMonitorServerId(instanceInfo.getMonitorServerId());
            assetInfo.setAssetMonitorStatus(instanceInfo.getMonitorStatus());
            assetInfo.setItemAssetsStatus(instanceInfo.getItemAssetsStatus());
            ZabbixAssetsStatusEnum assetsStatusEnum = ZabbixAssetsStatusEnum.getAssetsStatusEnumByName(instanceInfo.getItemAssetsStatus());
            if (assetsStatusEnum != null) {
                assetInfo.setItemAssetsStatusCode(assetsStatusEnum.getStatus());
            }
            assetInfo.setUserIds(instanceInfo.getUsers());
            assetInfo.setInBandIp(instanceInfo.getInBandIp());
            assetInfo.setPath(StringUtils.collectionToCommaDelimitedString(instanceInfo.getPath()));
            Map<String, Object> data = instanceInfo.getData();
            if (data != null) {
                Object msSystem = data.get(modelSystem);
                if (msSystem != null && msSystem instanceof Map) {
                    Map<String, String> map = (Map) msSystem;
                    String relationId = map.get(relationIdKey);
                    String relationName = map.get(relationNameKey);
                    assetInfo.setModelSystemId(relationId);
                    assetInfo.setModelSystemName(relationName);
                }
                Object msClassify = data.get(modelClassify);
                if(msClassify!=null && msClassify instanceof Map){
                    Map<String,String> map = (Map)msClassify;
                    String relationId = map.get(relationIdKey);
                    String relationName =  map.get(relationNameKey);
                    assetInfo.setModelClassifyId(relationId);
                    assetInfo.setModelClassifyName(relationName);
                }
            }

            if (instanceInfo.getOrgIds() != null) {
                assetInfo.setOrgIdsStr(JSON.toJSONString(instanceInfo.getOrgIds().stream().map(Object::toString).toList()));
            }
            if (instanceInfo.getGroups() != null) {
                assetInfo.setGroupsStr(JSON.toJSONString(instanceInfo.getGroups().stream().map(Object::toString).toList()));
            }
            if (instanceInfo.getOrgs() != null) {
                assetInfo.setOrgsStr(JSON.toJSONString(instanceInfo.getOrgs().stream().map(innerList -> innerList.stream().map(Object::toString).toList()).toList()));
            }
            if (instanceInfo.getUsers() != null) {
                assetInfo.setUsersStr(JSON.toJSONString(instanceInfo.getUsers().stream().map(Object::toString).toList()));
            }

            if (StringUtils.hasText(instanceInfo.getPollingEngine())) {
                assetInfo.setPollingEngine(instanceInfo.getPollingEngine());
                assetInfo.setProxyType(instanceInfo.getProxyType());
            }

            //设置监控信息
            String ruleType = instanceInfo.getRuleType();
            if (StringUtils.hasText(ruleType)) {
                MonitorInfo monitorInfo = new MonitorInfo();
                monitorInfo.setRuleType(ruleType);
                monitorInfo.setSecurityName(instanceInfo.getSecurityName());
                monitorInfo.setSecurityLevel(instanceInfo.getSecurityLevel());
                monitorInfo.setPort(instanceInfo.getPort());
                monitorInfo.setCommunity(instanceInfo.getCommunity());
                monitorInfo.setContextName(instanceInfo.getContextName());
                monitorInfo.setAuthAlgName(instanceInfo.getAuthAlgName());
                monitorInfo.setAuthValue(instanceInfo.getAuthValue());
                monitorInfo.setPrivAlgName(instanceInfo.getPrivAlgName());
                monitorInfo.setPriValue(instanceInfo.getPriValue());
                assetInfo.setMonitorInfo(monitorInfo);
            }
            assetInfos.add(assetInfo);
        }
        return assetInfos;
    }

    /**
     * 更新资产告警状态
     *
     * @param instanceId
     * @param alertLevel
     * @throws Exception
     */
    @Override
    public void updateInstanceMonitorStatus(String instanceId, String alertLevel) throws Exception {
        log.info("updateInstanceMonitorStatus::instanceId:" + instanceId + "；alertLevel::" + alertLevel);
        //告警等级为"告警", "严重", "紧急"，修改资产状态
        if (!Strings.isNullOrEmpty(alertLevel) && alertLevelList.contains(alertLevel)) {
            InstanceServiceImpl viewService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
            log.info("updateInstanceMonitorStatus::going");
            viewService.updateInstanceAlertStatus(instanceId);
        }
    }

    /**
     * 恢复资产告警状态
     *
     * @param instanceId
     * @throws Exception
     */
    @Override
    public void recoverInstanceMonitorStatus(String instanceId) throws Exception {
        log.info("recoverInstanceMonitorStatus::instanceId:" + instanceId);
        InstanceServiceImpl viewService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        log.info("recoverInstanceMonitorStatus::going");
        viewService.recoverInstanceMonitorStatus(instanceId);
    }

    /**
     * 获取所有纳管的资产数据
     * @return
     */
    @Override
    public List<AssetInfo> getAllMonitorInstanceList() throws Exception {
        InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        InstanceSearchParam instanceSearchParam = new InstanceSearchParam();
        instanceSearchParam.setIgnoreDataAuth(true);
        List<InstanceInfoExtend> allMonitorInstanceList = instanceService.getAllMonitorInstanceList(instanceSearchParam);
        List<AssetInfo> assetInfos = convertParam(allMonitorInstanceList, false);
        return assetInfos;
    }

    @Override
    public void batchUpdateByInstanceMap(List<Map> list) throws Exception {
        InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        instanceService.batchUpdateByInstanceMap(list);
    }

    /**
     * 定时任务运行资产发现扫描
     * @param taskRuleId
     * @throws Exception
     */
    @Override
    public void assetsScanTaskExecute(String taskRuleId) throws Exception {
        InstanceRuleExecutorParam param = new InstanceRuleExecutorParam();
        AssetsDiscoverServiceImpl modelService = (AssetsDiscoverServiceImpl) cmdbServiceManage.getModelService(AssetsDiscoverServiceImpl.ID);
        param.setIds(Arrays.asList(taskRuleId));
        modelService.executorNow(param);
   }

}
